package be.dch.objectprops.parser;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import be.dch.objectprops.collector.Collector;
import be.dch.objectprops.formatter.Formatter;
import be.dch.util.StringUtils;

import com.google.inject.Inject;

public final class SimpleObjectParser implements Parser {
    private static final Logger LOG = Logger.getLogger(SimpleObjectParser.class);

    private final transient Map<Class<?>, Formatter> formatterMap = new HashMap<Class<?>, Formatter>();

    @Inject
    private Collector props;

    @Inject
    public SimpleObjectParser(final Set<Formatter> formatterList) {
	for (final Formatter formatter : formatterList) {
	    this.addFormatter(formatter);
	}
    }

    public void addFormatter(final Formatter format) {
	this.formatterMap.put(format.getFormatterClass(), format);
    }

    
    public boolean handleAsWriter(final Object result) {
	return this.formatterMap.containsKey(result.getClass());
    }

    
    public boolean handleAsReader(final Field field) {
	SimpleObjectParser.LOG.debug("Investigating of object can be handled");
	if (field == null) {
	    return false;
	}
	return this.formatterMap.containsKey(field.getType());
    }

    
    public void write(final Object result, final StringBuilder key) {
	this.props.setProperty(key.toString(), this.formatterMap.get(result.getClass()).format(result));

    }

    
    public void read(final StringBuilder key, final Field field, final Object result) {
	final int initialLength = key.length();
	final String value = this.props.getProperty(key.toString());
	SimpleObjectParser.LOG.debug("Setting value by using key: " + key.toString() + " with value " + value);
	if (!StringUtils.isEmpty(value) && !this.ignoreLoad(field)) {
	    final Object target = this.formatterMap.get(field.getType()).parse(value);
	    try {
		field.set(result, target);
	    } catch (final IllegalArgumentException e) {
		SimpleObjectParser.LOG.error(e);
	    } catch (final IllegalAccessException e) {
		SimpleObjectParser.LOG.error(e);
	    }
	}
	key.setLength(initialLength);

    }

    
    public Object read(final StringBuilder key, final Object result) {
	return null;
    }

    private boolean ignoreLoad(final Field field) {
	return (Modifier.isStatic(field.getModifiers())) || (Modifier.isTransient(field.getModifiers()));
    }
}
